Actionbook: Build Your First AI Browser Agent
In this tutorial you will build a small Node.js AI agent that uses the Actionbook CLI and Action Manuals to search Google β entirely on your local machine. By the end you will understand how action manuals provide pre-computed selectors, how the CLI controls your browser, and how to wire everything together with an LLM.
> What you will build: A command-line agent you run with node agent.mjs "your query". It fetches an action manual for Google, extracts the search input selector, opens your real browser, types the query, and takes a screenshot of the results.
How Actionbook Works
Without Actionbook an AI agent has to download an entire HTML page, parse it, and guess which element to click β burning tokens and hallucinating. Actionbook gives the agent Action Manuals instead: pre-computed playbooks with verified selectors for each interactive element on popular websites.
Your Agent β ββ actionbook search "google search" βββΊ Find available action manuals β β’ google.com:/:default β β’ google.com:/advanced_search:default β ββ actionbook get "google.com:/:default" βββ Full manual with selectors β β’ textarea_search: textarea[aria-label="Search"] β β’ button_search: [aria-label="Google Search"] β ββ actionbook browser open "google.com" βββΊ Your real Chrome/Edge/Brave β (connected via CDP β no driver install) β ββ actionbook browser fill / press βββΊ Execute actions using verified selectors
The CLI is written in Rust and connects to the browser you already have installed β nothing extra to download. Action manuals are maintained and versioned by Actionbook, so when a site changes, the manual is updated β not your agent.
Prerequisites
Before you start, make sure you have:
- Node.js 18+ β check with
node --version - Chrome, Brave, Edge, or Arc already installed on your machine
- An OpenAI API key (free tier works) β you will store it in
.env - A terminal (macOS Terminal, Windows PowerShell, or Linux shell)
Project Structure
Here is every file you will create in this tutorial:
my-actionbook-agent/ βββ agent.mjs β the AI agent that orchestrates everything βββ browser.mjs β thin wrapper around Actionbook CLI commands βββ .env β your API key (never commit this) βββ package.json
Step 1 β Install the Actionbook CLI
Open your terminal and run:
npm install -g @actionbookdev/cli
Verify the install worked:
actionbook --version
You should see a version number printed. If you see a "command not found" error, make sure your npm global bin directory is on your PATH (run npm bin -g to find it).
Step 2 β Try the CLI Manually
Before writing any code, letβs explore Actionbook interactively so you understand what your agent will do automatically.
Search for action manuals and explore them:# Search for Google-related action manuals actionbook search "google search" # Get the full action manual for Google homepage actionbook get "google.com:/:default"
# Open Google in your existing Chrome/Brave/Edge actionbook browser open "https://www.google.com" # Fill the search box using a selector from the action manual actionbook browser fill 'textarea[aria-label="Search"]' "Actionbook browser agent" # Press Enter to search actionbook browser press "Enter" # Take a screenshot to verify actionbook browser screenshot ./result.png # Always close when you are done actionbook browser close
> What just happened? The search command found available action manuals for Google. The get command retrieved the full manual with verified selectors. The CLI then connected to your real browser via Chrome DevTools Protocol (CDP) and executed the automation using those selectors. No WebDriver, no Selenium, no separate Chromium download β it used the browser you already have.
Step 3 β Create the Project
mkdir my-actionbook-agent cd my-actionbook-agent npm init -y npm install openai dotenv
package.json β add "type": "module" so you can use ES modules:
{ "name": "my-actionbook-agent", "version": "1.0.0", "type": "module", "scripts": { "start": "node agent.mjs" }, "dependencies": { "openai": "^4.0.0", "dotenv": "^16.0.0" } }
.env β paste your key here:
OPENAI_API_KEY=sk-your-key-here
Step 4 β browser.mjs β CLI Wrapper
This file wraps each Actionbook CLI command in a JavaScript function so your agent can call them easily.
// browser.mjs // Wraps Actionbook CLI commands so the agent can call them from JS. import { execSync } from "node:child_process"; // Run a CLI command and return its stdout as a string. // opts.stdio = "inherit" lets you see live output in the terminal. function run(cmd, opts = {}) { return execSync(cmd, { encoding: "utf8", ...opts }); } // ββ Action Manual Commands βββββββββββββββββββββββββββββββββββββββββββββββββββ /** Search for action manuals. Returns raw text output from the CLI. */ export function searchActions(query) { console.log(`[actionbook] Searching: "${query}"`); return run(`actionbook search "${query}"`); } /** Fetch the full action manual for an area ID (e.g. "google.com:/:default"). */ export function getManual(areaId) { console.log(`[actionbook] Getting manual: ${areaId}`); return run(`actionbook get "${areaId}"`); } // ββ Browser Commands βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ /** Open a URL in your existing Chrome/Brave/Edge browser. */ export function browserOpen(url) { console.log(`[actionbook] Opening: ${url}`); run(`actionbook browser open "${url}"`, { stdio: "inherit" }); } /** Fill an input field with text (official Actionbook command). */ export function browserFill(selector, text) { console.log(`[actionbook] Filling "${text}" into ${selector}`); // Use single quotes for selector to avoid escaping issues with attribute selectors run(`actionbook browser fill '${selector}' '${text}'`); } /** Press a key (e.g., "Enter", "Tab", "Escape"). */ export function browserPressKey(key) { console.log(`[actionbook] Pressing key: ${key}`); run(`actionbook browser press "${key}"`); } /** Take a screenshot. Returns path string. */ export function browserScreenshot(path = "./screenshot.png") { run(`actionbook browser screenshot "${path}"`); return path; } /** Close the browser session. ALWAYS call this when done. */ export function browserClose() { console.log(`[actionbook] Closing browser.`); try { run(`actionbook browser close`); } catch { // Ignore errors on close β browser may already be shut down. } }
Step 5 β agent.mjs β The AI Agent
This is the brain. It searches for an action manual, extracts the verified selector, then uses browser.mjs to execute the task.
// agent.mjs import "dotenv/config"; import OpenAI from "openai"; import { searchActions, getManual, browserOpen, browserFill, browserPressKey, browserScreenshot, browserClose, } from "./browser.mjs"; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); // ββ Step 1: Parse action IDs from search results ββββββββββββββββββββββββββββ function parseActionIds(searchOutput) { const lines = searchOutput.split("\n"); const actionIds = []; for (const line of lines) { // Match "- ID: xxx" format const idMatch = line.match(/^- ID:\s*(.+)$/); if (idMatch) { actionIds.push(idMatch[1].trim()); continue; } // Match "### xxx" header format const headerMatch = line.match(/^###\s+([\w.-]+:[^\s]+)/); if (headerMatch) { actionIds.push(headerMatch[1].trim()); } } return actionIds; } // ββ Step 2: Main search task using action manuals βββββββββββββββββββββββββββ async function runSearchTask(query) { console.log(`\nπ€ Agent starting task: search Google for "${query}"\n`); try { // Search for Google search action manual console.log("[agent] Searching for action manual..."); const searchResults = searchActions("google search"); // Parse action IDs from results const actionIds = parseActionIds(searchResults); console.log("[agent] Found action IDs:", actionIds); // Find the Google homepage action let actionId = actionIds.find((id) => id.startsWith("google.com:/:") || id === "google.com:/:default" ); if (!actionId) { actionId = actionIds.find((id) => id.startsWith("google.com:")); } if (!actionId) throw new Error("No action manual found for Google"); // Get the full action manual console.log(`[agent] Fetching manual for: ${actionId}`); const manual = getManual(actionId); // Extract the search input selector from the role definition // The manual contains: getByRole('combobox', { name: 'Search' }) let searchInputSelector = '[role="combobox"]'; const roleMatch = manual.match(/getByRole\('combobox',\s*\{\s*name:\s*'([^']+)'\s*\}\)/); if (roleMatch) { const comboboxName = roleMatch[1]; console.log(`[agent] Found combobox name: ${comboboxName}`); searchInputSelector = `textarea[aria-label="${comboboxName}"]`; } console.log(`[agent] Using selector: ${searchInputSelector}`); // Execute browser automation browserOpen("https://www.google.com"); await new Promise((resolve) => setTimeout(resolve, 1500)); // Fill the search input and submit browserFill(searchInputSelector, query); browserPressKey("Enter"); // Wait for results and screenshot await new Promise((resolve) => setTimeout(resolve, 3000)); const shot = browserScreenshot("./search-result.png"); console.log(`\nβ Done! Screenshot saved to ${shot}`); } finally { browserClose(); } } // ββ Entry point ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ const query = process.argv[2] ?? "Actionbook browser agent"; runSearchTask(query).catch((err) => { console.error("\nβ Agent error:", err.message); browserClose(); process.exit(1); });
Step 6 β Run the Agent
Make sure Chrome (or Brave/Edge) is installed, then run:
node agent.mjs "open source AI agents"
You will see the agent log each step as it goes:
π€ Agent starting task: search Google for "open source AI agents" [agent] Searching for action manual... [actionbook] Searching: "google search" [agent] Found action IDs: [ 'google.com:/:default', ... ] [agent] Fetching manual for: google.com:/:default [actionbook] Getting manual: google.com:/:default [agent] Found combobox name: Search [agent] Using selector: textarea[aria-label="Search"] [actionbook] Opening: https://www.google.com β Google https://www.google.com [actionbook] Filling "open source AI agents" into textarea[aria-label="Search"] [actionbook] Pressing key: Enter β Done! Screenshot saved to ./search-result.png [actionbook] Closing browser.
Open search-result.png and you will see a real Google results page.
Step 7 β Understand What Each Part Does
browser.mjsβ Translates JS function calls intoactionbookCLI commands (search, get, browser fill, etc.)agent.mjsβ Orchestrates the workflow: search for manual β get manual β extract selector β execute browser actions.envβ Stores secrets β never commit this file
What is CDP? Chrome DevTools Protocol is the same protocol your browser's DevTools uses. Actionbook speaks CDP natively, so it can open tabs, click, type, and screenshot without any driver or browser extension.
Next Steps
Now that your first agent works, here is what to try next:
- Add more sites β run
actionbook search "linkedin login"and automate LinkedIn. - Loop over queries β read a list of search terms from a file and run the agent for each.
- Chain actions β after the search, get another manual for the results page and follow a link.
- Add the MCP server β once comfortable with the CLI, add the MCP server to Cursor or Claude Code so your AI IDE can call Actionbook for you automatically.
Resources
- Actionbook GitHub β source code, issue tracker
- Actionbook Docs β full CLI and MCP reference
- Discord Community β ask questions, share agents
- Request a Website β suggest sites to index